package com.atguigu.tingshu.album.listen;

import com.alibaba.nacos.common.utils.JacksonUtils;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.constant.TingShuMqConstants;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.order.OrderDetail;
import com.atguigu.tingshu.model.order.OrderInfo;
import com.atguigu.tingshu.order.client.OrderInfoFeignClient;
import com.atguigu.tingshu.vo.album.TrackStatMqVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rabbitmq.client.Channel;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class AlbumListener {
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private TrackStatMapper trackStatMapper;
    @Resource
    private AlbumStatMapper albumStatMapper;
    @Resource
    private OrderInfoFeignClient orderInfoFeignClient;
    @Resource
    private TrackInfoMapper trackInfoMapper;

    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = TingShuMqConstants.MXW_EXCHANGE, type = ExchangeTypes.TOPIC, ignoreDeclarationExceptions = "true"),
            value = @Queue(value = TingShuMqConstants.MXW_QUEUE),
            key = TingShuMqConstants.MXW_RK
    ))
    public void mxwListener(String json, Channel channel, Message message) throws IOException {
        System.out.println(json);
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    @RabbitListener(bindings = {@QueueBinding(
            exchange = @Exchange(value = TingShuMqConstants.USER_EXCHANGE, type = ExchangeTypes.TOPIC, ignoreDeclarationExceptions = "true"),
            value = @Queue(value = TingShuMqConstants.TRACK_STAT_QUEUE),
            key = TingShuMqConstants.TRACK_STAT_RK
    )})
    public void trackStatListener(String jsonStr, Channel channel, Message msg) throws IOException {

        if (StringUtils.isBlank(jsonStr)) {
            channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
            return;
        }
        TrackStatMqVo mqVo = JacksonUtils.toObj(jsonStr, TrackStatMqVo.class);
        //幂等性校验
        LocalTime endTime = LocalDateTime.of(LocalDate.now(), LocalTime.MAX).toLocalTime();
        long timeOut = ChronoUnit.MILLIS.between(LocalTime.now(), endTime);
        redisTemplate.opsForValue().setIfAbsent(RedisConstant.TRACK_STAT_LOCK_SUFFIX + mqVo.getBusinessNo(), "",
                timeOut, TimeUnit.SECONDS);
        //获取声音的播放量信息
        TrackStat trackStat = trackStatMapper.selectOne(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, mqVo.getTrackId())
                .eq(TrackStat::getStatType, mqVo.getStatType()));
        if (trackStat == null) {
            trackStat = new TrackStat();
            trackStat.setTrackId(mqVo.getTrackId());
            trackStat.setStatType(mqVo.getStatType());
            trackStat.setStatNum(mqVo.getCount());
            //保存播放量信息
            trackStatMapper.insert(trackStat);
        } else {
            trackStat.setStatNum(trackStat.getStatNum() + mqVo.getCount());
            //更新播放量信息
            trackStatMapper.updateById(trackStat);
        }

        //判断如果保存的是声音的播放量或者是评论数时，需要同步专辑的播放量和评论数
        AlbumStat albumStat = null;
        switch (mqVo.getStatType()) {
            case SystemConstant.TRACK_STAT_PLAY -> {
                albumStat = albumStatMapper.selectOne(new LambdaQueryWrapper<AlbumStat>()
                        .eq(AlbumStat::getAlbumId, mqVo.getAlbumId())
                        .eq(AlbumStat::getStatType, SystemConstant.ALBUM_STAT_PLAY));
                albumStat.setStatNum(albumStat.getStatNum() + mqVo.getCount());
            }
            case SystemConstant.TRACK_STAT_COMMENT -> {
                albumStat = albumStatMapper.selectOne(new LambdaQueryWrapper<AlbumStat>()
                        .eq(AlbumStat::getAlbumId, mqVo.getAlbumId())
                        .eq(AlbumStat::getStatType, SystemConstant.ALBUM_STAT_COMMENT));
                albumStat.setStatNum(albumStat.getStatNum() + mqVo.getCount());
            }
        }
        albumStatMapper.updateById(albumStat);
        channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
    }

    @RabbitListener(bindings = {@QueueBinding(
            exchange = @Exchange(value = TingShuMqConstants.USER_EXCHANGE, type = ExchangeTypes.TOPIC, ignoreDeclarationExceptions = "true"),
            value = @Queue(value = TingShuMqConstants.PAID_STAT_QUEUE),
            key = TingShuMqConstants.PAID_STAT_RK
    )})
    public void albumStatListener(String orderNo, Channel channel, Message message) throws IOException {
        if (StringUtils.isBlank(orderNo)) {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }
        //幂等性校验
        String itemKey = RedisConstant.ALBUM_ITEM_PREFIX + orderNo;
        Boolean flag = this.redisTemplate.opsForValue().setIfAbsent(itemKey, "", RedisConstant.ITEM_TIMEOUT, TimeUnit.SECONDS);
        if (Boolean.FALSE.equals(flag)) {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }
        //查询订单信息
        Result<OrderInfo> orderInfoResult = this.orderInfoFeignClient.getOrderInfo(orderNo);
        Assert.notNull(orderInfoResult, "保存购买量时，获取订单信息失败！");
        OrderInfo orderInfo = orderInfoResult.getData();

        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        List<Long> itemIds = orderDetailList.stream().map(OrderDetail::getItemId).toList();

        switch (orderInfo.getItemType()) {
            case SystemConstant.ORDER_ITEM_TYPE_ALBUM -> {
                AlbumStat albumStat = this.albumStatMapper.selectOne(new LambdaQueryWrapper<AlbumStat>()
                        .eq(AlbumStat::getAlbumId, itemIds.get(0))
                        .eq(AlbumStat::getStatType, SystemConstant.ALBUM_STAT_BROWSE));
                albumStat.setStatNum(albumStat.getStatNum() + 1);
                this.albumStatMapper.updateById(albumStat);
            }
            case SystemConstant.ORDER_ITEM_TYPE_TRACK -> {
                TrackInfo trackInfo = this.trackInfoMapper.selectById(itemIds.get(0));
                //更新专辑的购买量
                AlbumStat albumStat = this.albumStatMapper.selectOne(new LambdaQueryWrapper<AlbumStat>()
                        .eq(AlbumStat::getAlbumId, trackInfo.getAlbumId())
                        .eq(AlbumStat::getStatType, SystemConstant.ALBUM_STAT_BROWSE));
                albumStat.setStatNum(albumStat.getStatNum() + 1);
                this.albumStatMapper.updateById(albumStat);
            }
        }
    }
}
